//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension Kinesis {
    // MARK: Enums

    public enum ConsumerStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        case active = "ACTIVE"
        case creating = "CREATING"
        case deleting = "DELETING"
        public var description: String { return self.rawValue }
    }

    public enum EncryptionType: String, CustomStringConvertible, Codable, _SotoSendable {
        case kms = "KMS"
        case none = "NONE"
        public var description: String { return self.rawValue }
    }

    public enum MetricsName: String, CustomStringConvertible, Codable, _SotoSendable {
        case all = "ALL"
        case incomingBytes = "IncomingBytes"
        case incomingRecords = "IncomingRecords"
        case iteratorAgeMilliseconds = "IteratorAgeMilliseconds"
        case outgoingBytes = "OutgoingBytes"
        case outgoingRecords = "OutgoingRecords"
        case readProvisionedThroughputExceeded = "ReadProvisionedThroughputExceeded"
        case writeProvisionedThroughputExceeded = "WriteProvisionedThroughputExceeded"
        public var description: String { return self.rawValue }
    }

    public enum ScalingType: String, CustomStringConvertible, Codable, _SotoSendable {
        case uniformScaling = "UNIFORM_SCALING"
        public var description: String { return self.rawValue }
    }

    public enum ShardFilterType: String, CustomStringConvertible, Codable, _SotoSendable {
        case afterShardId = "AFTER_SHARD_ID"
        case atLatest = "AT_LATEST"
        case atTimestamp = "AT_TIMESTAMP"
        case atTrimHorizon = "AT_TRIM_HORIZON"
        case fromTimestamp = "FROM_TIMESTAMP"
        case fromTrimHorizon = "FROM_TRIM_HORIZON"
        public var description: String { return self.rawValue }
    }

    public enum ShardIteratorType: String, CustomStringConvertible, Codable, _SotoSendable {
        case afterSequenceNumber = "AFTER_SEQUENCE_NUMBER"
        case atSequenceNumber = "AT_SEQUENCE_NUMBER"
        case atTimestamp = "AT_TIMESTAMP"
        case latest = "LATEST"
        case trimHorizon = "TRIM_HORIZON"
        public var description: String { return self.rawValue }
    }

    public enum StreamMode: String, CustomStringConvertible, Codable, _SotoSendable {
        case onDemand = "ON_DEMAND"
        case provisioned = "PROVISIONED"
        public var description: String { return self.rawValue }
    }

    public enum StreamStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        case active = "ACTIVE"
        case creating = "CREATING"
        case deleting = "DELETING"
        case updating = "UPDATING"
        public var description: String { return self.rawValue }
    }

    public enum SubscribeToShardEventStream: AWSDecodableShape, _SotoSendable {
        /// The processing of the request failed because of an unknown error, exception, or failure.
        case internalFailureException(InternalFailureException)
        case kmsAccessDeniedException(KMSAccessDeniedException)
        case kmsDisabledException(KMSDisabledException)
        case kmsInvalidStateException(KMSInvalidStateException)
        case kmsNotFoundException(KMSNotFoundException)
        case kmsOptInRequired(KMSOptInRequired)
        case kmsThrottlingException(KMSThrottlingException)
        case resourceInUseException(ResourceInUseException)
        case resourceNotFoundException(ResourceNotFoundException)
        /// After you call SubscribeToShard, Kinesis Data Streams sends events of this type to your consumer. For an example of how to handle these events, see Enhanced Fan-Out Using the Kinesis Data Streams API.
        case subscribeToShardEvent(SubscribeToShardEvent)

        public init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            guard container.allKeys.count == 1, let key = container.allKeys.first else {
                let context = DecodingError.Context(
                    codingPath: container.codingPath,
                    debugDescription: "Expected exactly one key, but got \(container.allKeys.count)"
                )
                throw DecodingError.dataCorrupted(context)
            }
            switch key {
            case .internalFailureException:
                let value = try container.decode(InternalFailureException.self, forKey: .internalFailureException)
                self = .internalFailureException(value)
            case .kmsAccessDeniedException:
                let value = try container.decode(KMSAccessDeniedException.self, forKey: .kmsAccessDeniedException)
                self = .kmsAccessDeniedException(value)
            case .kmsDisabledException:
                let value = try container.decode(KMSDisabledException.self, forKey: .kmsDisabledException)
                self = .kmsDisabledException(value)
            case .kmsInvalidStateException:
                let value = try container.decode(KMSInvalidStateException.self, forKey: .kmsInvalidStateException)
                self = .kmsInvalidStateException(value)
            case .kmsNotFoundException:
                let value = try container.decode(KMSNotFoundException.self, forKey: .kmsNotFoundException)
                self = .kmsNotFoundException(value)
            case .kmsOptInRequired:
                let value = try container.decode(KMSOptInRequired.self, forKey: .kmsOptInRequired)
                self = .kmsOptInRequired(value)
            case .kmsThrottlingException:
                let value = try container.decode(KMSThrottlingException.self, forKey: .kmsThrottlingException)
                self = .kmsThrottlingException(value)
            case .resourceInUseException:
                let value = try container.decode(ResourceInUseException.self, forKey: .resourceInUseException)
                self = .resourceInUseException(value)
            case .resourceNotFoundException:
                let value = try container.decode(ResourceNotFoundException.self, forKey: .resourceNotFoundException)
                self = .resourceNotFoundException(value)
            case .subscribeToShardEvent:
                let value = try container.decode(SubscribeToShardEvent.self, forKey: .subscribeToShardEvent)
                self = .subscribeToShardEvent(value)
            }
        }

        private enum CodingKeys: String, CodingKey {
            case internalFailureException = "InternalFailureException"
            case kmsAccessDeniedException = "KMSAccessDeniedException"
            case kmsDisabledException = "KMSDisabledException"
            case kmsInvalidStateException = "KMSInvalidStateException"
            case kmsNotFoundException = "KMSNotFoundException"
            case kmsOptInRequired = "KMSOptInRequired"
            case kmsThrottlingException = "KMSThrottlingException"
            case resourceInUseException = "ResourceInUseException"
            case resourceNotFoundException = "ResourceNotFoundException"
            case subscribeToShardEvent = "SubscribeToShardEvent"
        }
    }

    // MARK: Shapes

    public struct AddTagsToStreamInput: AWSEncodableShape {
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream.
        public let streamName: String?
        /// A set of up to 10 key-value pairs to use to create the tags.
        public let tags: [String: String]

        public init(streamARN: String? = nil, streamName: String? = nil, tags: [String: String]) {
            self.streamARN = streamARN
            self.streamName = streamName
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
            try self.validate(self.tags, name: "tags", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case streamARN = "StreamARN"
            case streamName = "StreamName"
            case tags = "Tags"
        }
    }

    public struct ChildShard: AWSDecodableShape {
        public let hashKeyRange: HashKeyRange
        /// The current shard that is the parent of the existing child shard.
        public let parentShards: [String]
        /// The shard ID of the existing child shard of the current shard.
        public let shardId: String

        public init(hashKeyRange: HashKeyRange, parentShards: [String], shardId: String) {
            self.hashKeyRange = hashKeyRange
            self.parentShards = parentShards
            self.shardId = shardId
        }

        private enum CodingKeys: String, CodingKey {
            case hashKeyRange = "HashKeyRange"
            case parentShards = "ParentShards"
            case shardId = "ShardId"
        }
    }

    public struct Consumer: AWSDecodableShape {
        /// When you register a consumer, Kinesis Data Streams generates an ARN for it. You need this ARN to be able to call SubscribeToShard. If you delete a consumer and then create a new one with the same name, it won't have the same ARN. That's because consumer ARNs contain the creation timestamp. This is important to keep in mind if you have IAM policies that reference consumer ARNs.
        public let consumerARN: String
        public let consumerCreationTimestamp: Date
        /// The name of the consumer is something you choose when you register the consumer.
        public let consumerName: String
        /// A consumer can't read data while in the CREATING or DELETING states.
        public let consumerStatus: ConsumerStatus

        public init(consumerARN: String, consumerCreationTimestamp: Date, consumerName: String, consumerStatus: ConsumerStatus) {
            self.consumerARN = consumerARN
            self.consumerCreationTimestamp = consumerCreationTimestamp
            self.consumerName = consumerName
            self.consumerStatus = consumerStatus
        }

        private enum CodingKeys: String, CodingKey {
            case consumerARN = "ConsumerARN"
            case consumerCreationTimestamp = "ConsumerCreationTimestamp"
            case consumerName = "ConsumerName"
            case consumerStatus = "ConsumerStatus"
        }
    }

    public struct ConsumerDescription: AWSDecodableShape {
        /// When you register a consumer, Kinesis Data Streams generates an ARN for it. You need this ARN to be able to call SubscribeToShard. If you delete a consumer and then create a new one with the same name, it won't have the same ARN. That's because consumer ARNs contain the creation timestamp. This is important to keep in mind if you have IAM policies that reference consumer ARNs.
        public let consumerARN: String
        public let consumerCreationTimestamp: Date
        /// The name of the consumer is something you choose when you register the consumer.
        public let consumerName: String
        /// A consumer can't read data while in the CREATING or DELETING states.
        public let consumerStatus: ConsumerStatus
        /// The ARN of the stream with which you registered the consumer.
        public let streamARN: String

        public init(consumerARN: String, consumerCreationTimestamp: Date, consumerName: String, consumerStatus: ConsumerStatus, streamARN: String) {
            self.consumerARN = consumerARN
            self.consumerCreationTimestamp = consumerCreationTimestamp
            self.consumerName = consumerName
            self.consumerStatus = consumerStatus
            self.streamARN = streamARN
        }

        private enum CodingKeys: String, CodingKey {
            case consumerARN = "ConsumerARN"
            case consumerCreationTimestamp = "ConsumerCreationTimestamp"
            case consumerName = "ConsumerName"
            case consumerStatus = "ConsumerStatus"
            case streamARN = "StreamARN"
        }
    }

    public struct CreateStreamInput: AWSEncodableShape {
        /// The number of shards that the stream will use. The throughput of the stream is a function of the number of shards; more shards are required for greater provisioned throughput.
        public let shardCount: Int?
        ///  Indicates the capacity mode of the data stream. Currently, in Kinesis Data Streams, you can choose between an on-demand capacity mode and a provisioned capacity mode for your data streams.
        public let streamModeDetails: StreamModeDetails?
        /// A name to identify the stream. The stream name is scoped to the Amazon Web Services account used by the application that creates the stream. It is also scoped by Amazon Web Services Region. That is, two streams in two different Amazon Web Services accounts can have the same name. Two streams in the same Amazon Web Services account but in two different Regions can also have the same name.
        public let streamName: String

        public init(shardCount: Int? = nil, streamModeDetails: StreamModeDetails? = nil, streamName: String) {
            self.shardCount = shardCount
            self.streamModeDetails = streamModeDetails
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.shardCount, name: "shardCount", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case shardCount = "ShardCount"
            case streamModeDetails = "StreamModeDetails"
            case streamName = "StreamName"
        }
    }

    public struct DecreaseStreamRetentionPeriodInput: AWSEncodableShape {
        /// The new retention period of the stream, in hours. Must be less than the current retention period.
        public let retentionPeriodHours: Int
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream to modify.
        public let streamName: String?

        public init(retentionPeriodHours: Int, streamARN: String? = nil, streamName: String? = nil) {
            self.retentionPeriodHours = retentionPeriodHours
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case retentionPeriodHours = "RetentionPeriodHours"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct DeleteStreamInput: AWSEncodableShape {
        /// If this parameter is unset (null) or if you set it to false, and the stream has registered consumers, the call to DeleteStream fails with a ResourceInUseException.
        public let enforceConsumerDeletion: Bool?
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream to delete.
        public let streamName: String?

        public init(enforceConsumerDeletion: Bool? = nil, streamARN: String? = nil, streamName: String? = nil) {
            self.enforceConsumerDeletion = enforceConsumerDeletion
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case enforceConsumerDeletion = "EnforceConsumerDeletion"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct DeregisterStreamConsumerInput: AWSEncodableShape {
        /// The ARN returned by Kinesis Data Streams when you registered the consumer. If you don't know the ARN of the consumer that you want to deregister, you can use the ListStreamConsumers operation to get a list of the descriptions of all the consumers that are currently registered with a given data stream. The description of a consumer contains its ARN.
        public let consumerARN: String?
        /// The name that you gave to the consumer.
        public let consumerName: String?
        /// The ARN of the Kinesis data stream that the consumer is registered with. For more information, see Amazon Resource Names (ARNs) and Amazon Web Services Service Namespaces.
        public let streamARN: String?

        public init(consumerARN: String? = nil, consumerName: String? = nil, streamARN: String? = nil) {
            self.consumerARN = consumerARN
            self.consumerName = consumerName
            self.streamARN = streamARN
        }

        public func validate(name: String) throws {
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, max: 2048)
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, min: 1)
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, pattern: "^(arn):aws.*:kinesis:.*:\\d{12}:.*stream\\/[a-zA-Z0-9_.-]+\\/consumer\\/[a-zA-Z0-9_.-]+:[0-9]+$")
            try self.validate(self.consumerName, name: "consumerName", parent: name, max: 128)
            try self.validate(self.consumerName, name: "consumerName", parent: name, min: 1)
            try self.validate(self.consumerName, name: "consumerName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
        }

        private enum CodingKeys: String, CodingKey {
            case consumerARN = "ConsumerARN"
            case consumerName = "ConsumerName"
            case streamARN = "StreamARN"
        }
    }

    public struct DescribeLimitsInput: AWSEncodableShape {
        public init() {}
    }

    public struct DescribeLimitsOutput: AWSDecodableShape {
        ///  Indicates the number of data streams with the on-demand capacity mode.
        public let onDemandStreamCount: Int
        ///  The maximum number of data streams with the on-demand capacity mode.
        public let onDemandStreamCountLimit: Int
        /// The number of open shards.
        public let openShardCount: Int
        /// The maximum number of shards.
        public let shardLimit: Int

        public init(onDemandStreamCount: Int, onDemandStreamCountLimit: Int, openShardCount: Int, shardLimit: Int) {
            self.onDemandStreamCount = onDemandStreamCount
            self.onDemandStreamCountLimit = onDemandStreamCountLimit
            self.openShardCount = openShardCount
            self.shardLimit = shardLimit
        }

        private enum CodingKeys: String, CodingKey {
            case onDemandStreamCount = "OnDemandStreamCount"
            case onDemandStreamCountLimit = "OnDemandStreamCountLimit"
            case openShardCount = "OpenShardCount"
            case shardLimit = "ShardLimit"
        }
    }

    public struct DescribeStreamConsumerInput: AWSEncodableShape {
        /// The ARN returned by Kinesis Data Streams when you registered the consumer.
        public let consumerARN: String?
        /// The name that you gave to the consumer.
        public let consumerName: String?
        /// The ARN of the Kinesis data stream that the consumer is registered with. For more information, see Amazon Resource Names (ARNs) and Amazon Web Services Service Namespaces.
        public let streamARN: String?

        public init(consumerARN: String? = nil, consumerName: String? = nil, streamARN: String? = nil) {
            self.consumerARN = consumerARN
            self.consumerName = consumerName
            self.streamARN = streamARN
        }

        public func validate(name: String) throws {
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, max: 2048)
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, min: 1)
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, pattern: "^(arn):aws.*:kinesis:.*:\\d{12}:.*stream\\/[a-zA-Z0-9_.-]+\\/consumer\\/[a-zA-Z0-9_.-]+:[0-9]+$")
            try self.validate(self.consumerName, name: "consumerName", parent: name, max: 128)
            try self.validate(self.consumerName, name: "consumerName", parent: name, min: 1)
            try self.validate(self.consumerName, name: "consumerName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
        }

        private enum CodingKeys: String, CodingKey {
            case consumerARN = "ConsumerARN"
            case consumerName = "ConsumerName"
            case streamARN = "StreamARN"
        }
    }

    public struct DescribeStreamConsumerOutput: AWSDecodableShape {
        /// An object that represents the details of the consumer.
        public let consumerDescription: ConsumerDescription

        public init(consumerDescription: ConsumerDescription) {
            self.consumerDescription = consumerDescription
        }

        private enum CodingKeys: String, CodingKey {
            case consumerDescription = "ConsumerDescription"
        }
    }

    public struct DescribeStreamInput: AWSEncodableShape {
        /// The shard ID of the shard to start with. Specify this parameter to indicate that you want to describe the stream starting with the shard whose ID immediately follows ExclusiveStartShardId. If you don't specify this parameter, the default behavior for DescribeStream is to describe the stream starting with the first shard in the stream.
        public let exclusiveStartShardId: String?
        /// The maximum number of shards to return in a single call. The default value is 100. If you specify a value greater than 100, at most 100 results are returned.
        public let limit: Int?
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream to describe.
        public let streamName: String?

        public init(exclusiveStartShardId: String? = nil, limit: Int? = nil, streamARN: String? = nil, streamName: String? = nil) {
            self.exclusiveStartShardId = exclusiveStartShardId
            self.limit = limit
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.exclusiveStartShardId, name: "exclusiveStartShardId", parent: name, max: 128)
            try self.validate(self.exclusiveStartShardId, name: "exclusiveStartShardId", parent: name, min: 1)
            try self.validate(self.exclusiveStartShardId, name: "exclusiveStartShardId", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.limit, name: "limit", parent: name, max: 10000)
            try self.validate(self.limit, name: "limit", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case exclusiveStartShardId = "ExclusiveStartShardId"
            case limit = "Limit"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct DescribeStreamOutput: AWSDecodableShape {
        /// The current status of the stream, the stream Amazon Resource Name (ARN), an array of shard objects that comprise the stream, and whether there are more shards available.
        public let streamDescription: StreamDescription

        public init(streamDescription: StreamDescription) {
            self.streamDescription = streamDescription
        }

        private enum CodingKeys: String, CodingKey {
            case streamDescription = "StreamDescription"
        }
    }

    public struct DescribeStreamSummaryInput: AWSEncodableShape {
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream to describe.
        public let streamName: String?

        public init(streamARN: String? = nil, streamName: String? = nil) {
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct DescribeStreamSummaryOutput: AWSDecodableShape {
        /// A StreamDescriptionSummary containing information about the stream.
        public let streamDescriptionSummary: StreamDescriptionSummary

        public init(streamDescriptionSummary: StreamDescriptionSummary) {
            self.streamDescriptionSummary = streamDescriptionSummary
        }

        private enum CodingKeys: String, CodingKey {
            case streamDescriptionSummary = "StreamDescriptionSummary"
        }
    }

    public struct DisableEnhancedMonitoringInput: AWSEncodableShape {
        /// List of shard-level metrics to disable. The following are the valid shard-level metrics. The value "ALL" disables every metric.    IncomingBytes     IncomingRecords     OutgoingBytes     OutgoingRecords     WriteProvisionedThroughputExceeded     ReadProvisionedThroughputExceeded     IteratorAgeMilliseconds     ALL    For more information, see Monitoring the Amazon Kinesis Data Streams Service with Amazon CloudWatch in the Amazon Kinesis Data Streams Developer Guide.
        public let shardLevelMetrics: [MetricsName]
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the Kinesis data stream for which to disable enhanced monitoring.
        public let streamName: String?

        public init(shardLevelMetrics: [MetricsName], streamARN: String? = nil, streamName: String? = nil) {
            self.shardLevelMetrics = shardLevelMetrics
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.shardLevelMetrics, name: "shardLevelMetrics", parent: name, max: 7)
            try self.validate(self.shardLevelMetrics, name: "shardLevelMetrics", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case shardLevelMetrics = "ShardLevelMetrics"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct EnableEnhancedMonitoringInput: AWSEncodableShape {
        /// List of shard-level metrics to enable. The following are the valid shard-level metrics. The value "ALL" enables every metric.    IncomingBytes     IncomingRecords     OutgoingBytes     OutgoingRecords     WriteProvisionedThroughputExceeded     ReadProvisionedThroughputExceeded     IteratorAgeMilliseconds     ALL    For more information, see Monitoring the Amazon Kinesis Data Streams Service with Amazon CloudWatch in the Amazon Kinesis Data Streams Developer Guide.
        public let shardLevelMetrics: [MetricsName]
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream for which to enable enhanced monitoring.
        public let streamName: String?

        public init(shardLevelMetrics: [MetricsName], streamARN: String? = nil, streamName: String? = nil) {
            self.shardLevelMetrics = shardLevelMetrics
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.shardLevelMetrics, name: "shardLevelMetrics", parent: name, max: 7)
            try self.validate(self.shardLevelMetrics, name: "shardLevelMetrics", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case shardLevelMetrics = "ShardLevelMetrics"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct EnhancedMetrics: AWSDecodableShape {
        /// List of shard-level metrics. The following are the valid shard-level metrics. The value "ALL" enhances every metric.    IncomingBytes     IncomingRecords     OutgoingBytes     OutgoingRecords     WriteProvisionedThroughputExceeded     ReadProvisionedThroughputExceeded     IteratorAgeMilliseconds     ALL    For more information, see Monitoring the Amazon Kinesis Data Streams Service with Amazon CloudWatch in the Amazon Kinesis Data Streams Developer Guide.
        public let shardLevelMetrics: [MetricsName]?

        public init(shardLevelMetrics: [MetricsName]? = nil) {
            self.shardLevelMetrics = shardLevelMetrics
        }

        private enum CodingKeys: String, CodingKey {
            case shardLevelMetrics = "ShardLevelMetrics"
        }
    }

    public struct EnhancedMonitoringOutput: AWSDecodableShape {
        /// Represents the current state of the metrics that are in the enhanced state before the operation.
        public let currentShardLevelMetrics: [MetricsName]?
        /// Represents the list of all the metrics that would be in the enhanced state after the operation.
        public let desiredShardLevelMetrics: [MetricsName]?
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the Kinesis data stream.
        public let streamName: String?

        public init(currentShardLevelMetrics: [MetricsName]? = nil, desiredShardLevelMetrics: [MetricsName]? = nil, streamARN: String? = nil, streamName: String? = nil) {
            self.currentShardLevelMetrics = currentShardLevelMetrics
            self.desiredShardLevelMetrics = desiredShardLevelMetrics
            self.streamARN = streamARN
            self.streamName = streamName
        }

        private enum CodingKeys: String, CodingKey {
            case currentShardLevelMetrics = "CurrentShardLevelMetrics"
            case desiredShardLevelMetrics = "DesiredShardLevelMetrics"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct GetRecordsInput: AWSEncodableShape {
        /// The maximum number of records to return. Specify a value of up to 10,000. If you specify a value that is greater than 10,000, GetRecords throws InvalidArgumentException. The default value is 10,000.
        public let limit: Int?
        /// The position in the shard from which you want to start sequentially reading data records. A shard iterator specifies this position using the sequence number of a data record in the shard.
        public let shardIterator: String
        /// The ARN of the stream.
        public let streamARN: String?

        public init(limit: Int? = nil, shardIterator: String, streamARN: String? = nil) {
            self.limit = limit
            self.shardIterator = shardIterator
            self.streamARN = streamARN
        }

        public func validate(name: String) throws {
            try self.validate(self.limit, name: "limit", parent: name, max: 10000)
            try self.validate(self.limit, name: "limit", parent: name, min: 1)
            try self.validate(self.shardIterator, name: "shardIterator", parent: name, max: 512)
            try self.validate(self.shardIterator, name: "shardIterator", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
        }

        private enum CodingKeys: String, CodingKey {
            case limit = "Limit"
            case shardIterator = "ShardIterator"
            case streamARN = "StreamARN"
        }
    }

    public struct GetRecordsOutput: AWSDecodableShape {
        /// The list of the current shard's child shards, returned in the GetRecords API's response only when the end of the current shard is reached.
        public let childShards: [ChildShard]?
        /// The number of milliseconds the GetRecords response is from the tip of the stream, indicating how far behind current time the consumer is. A value of zero indicates that record processing is caught up, and there are no new records to process at this moment.
        public let millisBehindLatest: Int64?
        /// The next position in the shard from which to start sequentially reading data records. If set to null, the shard has been closed and the requested iterator does not return any more data.
        public let nextShardIterator: String?
        /// The data records retrieved from the shard.
        public let records: [Record]

        public init(childShards: [ChildShard]? = nil, millisBehindLatest: Int64? = nil, nextShardIterator: String? = nil, records: [Record]) {
            self.childShards = childShards
            self.millisBehindLatest = millisBehindLatest
            self.nextShardIterator = nextShardIterator
            self.records = records
        }

        private enum CodingKeys: String, CodingKey {
            case childShards = "ChildShards"
            case millisBehindLatest = "MillisBehindLatest"
            case nextShardIterator = "NextShardIterator"
            case records = "Records"
        }
    }

    public struct GetShardIteratorInput: AWSEncodableShape {
        /// The shard ID of the Kinesis Data Streams shard to get the iterator for.
        public let shardId: String
        /// Determines how the shard iterator is used to start reading data records from the shard. The following are the valid Amazon Kinesis shard iterator types:   AT_SEQUENCE_NUMBER - Start reading from the position denoted by a specific sequence number, provided in the value StartingSequenceNumber.   AFTER_SEQUENCE_NUMBER - Start reading right after the position denoted by a specific sequence number, provided in the value StartingSequenceNumber.   AT_TIMESTAMP - Start reading from the position denoted by a specific time stamp, provided in the value Timestamp.   TRIM_HORIZON - Start reading at the last untrimmed record in the shard in the system, which is the oldest data record in the shard.   LATEST - Start reading just after the most recent record in the shard, so that you always read the most recent data in the shard.
        public let shardIteratorType: ShardIteratorType
        /// The sequence number of the data record in the shard from which to start reading. Used with shard iterator type AT_SEQUENCE_NUMBER and AFTER_SEQUENCE_NUMBER.
        public let startingSequenceNumber: String?
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the Amazon Kinesis data stream.
        public let streamName: String?
        /// The time stamp of the data record from which to start reading. Used with shard iterator type AT_TIMESTAMP. A time stamp is the Unix epoch date with precision in milliseconds. For example, 2016-04-04T19:58:46.480-00:00 or 1459799926.480. If a record with this exact time stamp does not exist, the iterator returned is for the next (later) record. If the time stamp is older than the current trim horizon, the iterator returned is for the oldest untrimmed data record (TRIM_HORIZON).
        public let timestamp: Date?

        public init(shardId: String, shardIteratorType: ShardIteratorType, startingSequenceNumber: String? = nil, streamARN: String? = nil, streamName: String? = nil, timestamp: Date? = nil) {
            self.shardId = shardId
            self.shardIteratorType = shardIteratorType
            self.startingSequenceNumber = startingSequenceNumber
            self.streamARN = streamARN
            self.streamName = streamName
            self.timestamp = timestamp
        }

        public func validate(name: String) throws {
            try self.validate(self.shardId, name: "shardId", parent: name, max: 128)
            try self.validate(self.shardId, name: "shardId", parent: name, min: 1)
            try self.validate(self.shardId, name: "shardId", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.startingSequenceNumber, name: "startingSequenceNumber", parent: name, pattern: "^0|([1-9]\\d{0,128})$")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case shardId = "ShardId"
            case shardIteratorType = "ShardIteratorType"
            case startingSequenceNumber = "StartingSequenceNumber"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
            case timestamp = "Timestamp"
        }
    }

    public struct GetShardIteratorOutput: AWSDecodableShape {
        /// The position in the shard from which to start reading data records sequentially. A shard iterator specifies this position using the sequence number of a data record in a shard.
        public let shardIterator: String?

        public init(shardIterator: String? = nil) {
            self.shardIterator = shardIterator
        }

        private enum CodingKeys: String, CodingKey {
            case shardIterator = "ShardIterator"
        }
    }

    public struct HashKeyRange: AWSDecodableShape {
        /// The ending hash key of the hash key range.
        public let endingHashKey: String
        /// The starting hash key of the hash key range.
        public let startingHashKey: String

        public init(endingHashKey: String, startingHashKey: String) {
            self.endingHashKey = endingHashKey
            self.startingHashKey = startingHashKey
        }

        private enum CodingKeys: String, CodingKey {
            case endingHashKey = "EndingHashKey"
            case startingHashKey = "StartingHashKey"
        }
    }

    public struct IncreaseStreamRetentionPeriodInput: AWSEncodableShape {
        /// The new retention period of the stream, in hours. Must be more than the current retention period.
        public let retentionPeriodHours: Int
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream to modify.
        public let streamName: String?

        public init(retentionPeriodHours: Int, streamARN: String? = nil, streamName: String? = nil) {
            self.retentionPeriodHours = retentionPeriodHours
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case retentionPeriodHours = "RetentionPeriodHours"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct InternalFailureException: AWSDecodableShape {
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct KMSAccessDeniedException: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct KMSDisabledException: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct KMSInvalidStateException: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct KMSNotFoundException: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct KMSOptInRequired: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct KMSThrottlingException: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct ListShardsInput: AWSEncodableShape {
        /// Specify this parameter to indicate that you want to list the shards starting with the shard whose ID immediately follows ExclusiveStartShardId. If you don't specify this parameter, the default behavior is for ListShards to list the shards starting with the first one in the stream. You cannot specify this parameter if you specify NextToken.
        public let exclusiveStartShardId: String?
        /// The maximum number of shards to return in a single call to ListShards. The maximum number of shards to return in a single call. The default value is 1000. If you specify a value greater than 1000, at most 1000 results are returned.  When the number of shards to be listed is greater than the value of MaxResults, the response contains a NextToken value that you can use in a subsequent call to ListShards to list the next set of shards.
        public let maxResults: Int?
        /// When the number of shards in the data stream is greater than the default value for the MaxResults parameter, or if you explicitly specify a value for MaxResults that is less than the number of shards in the data stream, the response includes a pagination token named NextToken. You can specify this NextToken value in a subsequent call to ListShards to list the next set of shards. Don't specify StreamName or StreamCreationTimestamp if you specify NextToken because the latter unambiguously identifies the stream. You can optionally specify a value for the MaxResults parameter when you specify NextToken. If you specify a MaxResults value that is less than the number of shards that the operation returns if you don't specify MaxResults, the response will contain a new NextToken value. You can use the new NextToken value in a subsequent call to the ListShards operation.  Tokens expire after 300 seconds. When you obtain a value for NextToken in the response to a call to ListShards, you have 300 seconds to use that value. If you specify an expired token in a call to ListShards, you get ExpiredNextTokenException.
        public let nextToken: String?
        /// Enables you to filter out the response of the ListShards API. You can only specify one filter at a time.  If you use the ShardFilter parameter when invoking the ListShards API, the Type is the required property and must be specified. If you specify the AT_TRIM_HORIZON, FROM_TRIM_HORIZON, or AT_LATEST types, you do not need to specify either the ShardId or the Timestamp optional properties.  If you specify the AFTER_SHARD_ID type, you must also provide the value for the optional ShardId property. The ShardId property is identical in fuctionality to the ExclusiveStartShardId parameter of the ListShards API. When ShardId property is specified, the response includes the shards starting with the shard whose ID immediately follows the ShardId that you provided.  If you specify the AT_TIMESTAMP or FROM_TIMESTAMP_ID type, you must also provide the value for the optional Timestamp property. If you specify the AT_TIMESTAMP type, then all shards that were open at the provided timestamp are returned. If you specify the FROM_TIMESTAMP type, then all shards starting from the provided timestamp to TIP are returned.
        public let shardFilter: ShardFilter?
        /// The ARN of the stream.
        public let streamARN: String?
        /// Specify this input parameter to distinguish data streams that have the same name. For example, if you create a data stream and then delete it, and you later create another data stream with the same name, you can use this input parameter to specify which of the two streams you want to list the shards for. You cannot specify this parameter if you specify the NextToken parameter.
        public let streamCreationTimestamp: Date?
        /// The name of the data stream whose shards you want to list.  You cannot specify this parameter if you specify the NextToken parameter.
        public let streamName: String?

        public init(exclusiveStartShardId: String? = nil, maxResults: Int? = nil, nextToken: String? = nil, shardFilter: ShardFilter? = nil, streamARN: String? = nil, streamCreationTimestamp: Date? = nil, streamName: String? = nil) {
            self.exclusiveStartShardId = exclusiveStartShardId
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.shardFilter = shardFilter
            self.streamARN = streamARN
            self.streamCreationTimestamp = streamCreationTimestamp
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.exclusiveStartShardId, name: "exclusiveStartShardId", parent: name, max: 128)
            try self.validate(self.exclusiveStartShardId, name: "exclusiveStartShardId", parent: name, min: 1)
            try self.validate(self.exclusiveStartShardId, name: "exclusiveStartShardId", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 10000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1_048_576)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.shardFilter?.validate(name: "\(name).shardFilter")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case exclusiveStartShardId = "ExclusiveStartShardId"
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
            case shardFilter = "ShardFilter"
            case streamARN = "StreamARN"
            case streamCreationTimestamp = "StreamCreationTimestamp"
            case streamName = "StreamName"
        }
    }

    public struct ListShardsOutput: AWSDecodableShape {
        /// When the number of shards in the data stream is greater than the default value for the MaxResults parameter, or if you explicitly specify a value for MaxResults that is less than the number of shards in the data stream, the response includes a pagination token named NextToken. You can specify this NextToken value in a subsequent call to ListShards to list the next set of shards. For more information about the use of this pagination token when calling the ListShards operation, see ListShardsInput$NextToken.  Tokens expire after 300 seconds. When you obtain a value for NextToken in the response to a call to ListShards, you have 300 seconds to use that value. If you specify an expired token in a call to ListShards, you get ExpiredNextTokenException.
        public let nextToken: String?
        /// An array of JSON objects. Each object represents one shard and specifies the IDs of the shard, the shard's parent, and the shard that's adjacent to the shard's parent. Each object also contains the starting and ending hash keys and the starting and ending sequence numbers for the shard.
        public let shards: [Shard]?

        public init(nextToken: String? = nil, shards: [Shard]? = nil) {
            self.nextToken = nextToken
            self.shards = shards
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "NextToken"
            case shards = "Shards"
        }
    }

    public struct ListStreamConsumersInput: AWSEncodableShape {
        /// The maximum number of consumers that you want a single call of ListStreamConsumers to return. The default value is 100. If you specify a value greater than 100, at most 100 results are returned.
        public let maxResults: Int?
        /// When the number of consumers that are registered with the data stream is greater than the default value for the MaxResults parameter, or if you explicitly specify a value for MaxResults that is less than the number of consumers that are registered with the data stream, the response includes a pagination token named NextToken. You can specify this NextToken value in a subsequent call to ListStreamConsumers to list the next set of registered consumers. Don't specify StreamName or StreamCreationTimestamp if you specify NextToken because the latter unambiguously identifies the stream. You can optionally specify a value for the MaxResults parameter when you specify NextToken. If you specify a MaxResults value that is less than the number of consumers that the operation returns if you don't specify MaxResults, the response will contain a new NextToken value. You can use the new NextToken value in a subsequent call to the ListStreamConsumers operation to list the next set of consumers.  Tokens expire after 300 seconds. When you obtain a value for NextToken in the response to a call to ListStreamConsumers, you have 300 seconds to use that value. If you specify an expired token in a call to ListStreamConsumers, you get ExpiredNextTokenException.
        public let nextToken: String?
        /// The ARN of the Kinesis data stream for which you want to list the registered consumers. For more information, see Amazon Resource Names (ARNs) and Amazon Web Services Service Namespaces.
        public let streamARN: String
        /// Specify this input parameter to distinguish data streams that have the same name. For example, if you create a data stream and then delete it, and you later create another data stream with the same name, you can use this input parameter to specify which of the two streams you want to list the consumers for.  You can't specify this parameter if you specify the NextToken parameter.
        public let streamCreationTimestamp: Date?

        public init(maxResults: Int? = nil, nextToken: String? = nil, streamARN: String, streamCreationTimestamp: Date? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.streamARN = streamARN
            self.streamCreationTimestamp = streamCreationTimestamp
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 10000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1_048_576)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
            case streamARN = "StreamARN"
            case streamCreationTimestamp = "StreamCreationTimestamp"
        }
    }

    public struct ListStreamConsumersOutput: AWSDecodableShape {
        /// An array of JSON objects. Each object represents one registered consumer.
        public let consumers: [Consumer]?
        /// When the number of consumers that are registered with the data stream is greater than the default value for the MaxResults parameter, or if you explicitly specify a value for MaxResults that is less than the number of registered consumers, the response includes a pagination token named NextToken. You can specify this NextToken value in a subsequent call to ListStreamConsumers to list the next set of registered consumers. For more information about the use of this pagination token when calling the ListStreamConsumers operation, see ListStreamConsumersInput$NextToken.  Tokens expire after 300 seconds. When you obtain a value for NextToken in the response to a call to ListStreamConsumers, you have 300 seconds to use that value. If you specify an expired token in a call to ListStreamConsumers, you get ExpiredNextTokenException.
        public let nextToken: String?

        public init(consumers: [Consumer]? = nil, nextToken: String? = nil) {
            self.consumers = consumers
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case consumers = "Consumers"
            case nextToken = "NextToken"
        }
    }

    public struct ListStreamsInput: AWSEncodableShape {
        /// The name of the stream to start the list with.
        public let exclusiveStartStreamName: String?
        /// The maximum number of streams to list. The default value is 100. If you specify a value greater than 100, at most 100 results are returned.
        public let limit: Int?
        public let nextToken: String?

        public init(exclusiveStartStreamName: String? = nil, limit: Int? = nil, nextToken: String? = nil) {
            self.exclusiveStartStreamName = exclusiveStartStreamName
            self.limit = limit
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.exclusiveStartStreamName, name: "exclusiveStartStreamName", parent: name, max: 128)
            try self.validate(self.exclusiveStartStreamName, name: "exclusiveStartStreamName", parent: name, min: 1)
            try self.validate(self.exclusiveStartStreamName, name: "exclusiveStartStreamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.limit, name: "limit", parent: name, max: 10000)
            try self.validate(self.limit, name: "limit", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1_048_576)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case exclusiveStartStreamName = "ExclusiveStartStreamName"
            case limit = "Limit"
            case nextToken = "NextToken"
        }
    }

    public struct ListStreamsOutput: AWSDecodableShape {
        /// If set to true, there are more streams available to list.
        public let hasMoreStreams: Bool
        public let nextToken: String?
        /// The names of the streams that are associated with the Amazon Web Services account making the ListStreams request.
        public let streamNames: [String]
        public let streamSummaries: [StreamSummary]?

        public init(hasMoreStreams: Bool, nextToken: String? = nil, streamNames: [String], streamSummaries: [StreamSummary]? = nil) {
            self.hasMoreStreams = hasMoreStreams
            self.nextToken = nextToken
            self.streamNames = streamNames
            self.streamSummaries = streamSummaries
        }

        private enum CodingKeys: String, CodingKey {
            case hasMoreStreams = "HasMoreStreams"
            case nextToken = "NextToken"
            case streamNames = "StreamNames"
            case streamSummaries = "StreamSummaries"
        }
    }

    public struct ListTagsForStreamInput: AWSEncodableShape {
        /// The key to use as the starting point for the list of tags. If this parameter is set, ListTagsForStream gets all tags that occur after ExclusiveStartTagKey.
        public let exclusiveStartTagKey: String?
        /// The number of tags to return. If this number is less than the total number of tags associated with the stream, HasMoreTags is set to true. To list additional tags, set ExclusiveStartTagKey to the last key in the response.
        public let limit: Int?
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream.
        public let streamName: String?

        public init(exclusiveStartTagKey: String? = nil, limit: Int? = nil, streamARN: String? = nil, streamName: String? = nil) {
            self.exclusiveStartTagKey = exclusiveStartTagKey
            self.limit = limit
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.exclusiveStartTagKey, name: "exclusiveStartTagKey", parent: name, max: 128)
            try self.validate(self.exclusiveStartTagKey, name: "exclusiveStartTagKey", parent: name, min: 1)
            try self.validate(self.limit, name: "limit", parent: name, max: 50)
            try self.validate(self.limit, name: "limit", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case exclusiveStartTagKey = "ExclusiveStartTagKey"
            case limit = "Limit"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct ListTagsForStreamOutput: AWSDecodableShape {
        /// If set to true, more tags are available. To request additional tags, set ExclusiveStartTagKey to the key of the last tag returned.
        public let hasMoreTags: Bool
        /// A list of tags associated with StreamName, starting with the first tag after ExclusiveStartTagKey and up to the specified Limit.
        public let tags: [Tag]

        public init(hasMoreTags: Bool, tags: [Tag]) {
            self.hasMoreTags = hasMoreTags
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case hasMoreTags = "HasMoreTags"
            case tags = "Tags"
        }
    }

    public struct MergeShardsInput: AWSEncodableShape {
        /// The shard ID of the adjacent shard for the merge.
        public let adjacentShardToMerge: String
        /// The shard ID of the shard to combine with the adjacent shard for the merge.
        public let shardToMerge: String
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream for the merge.
        public let streamName: String?

        public init(adjacentShardToMerge: String, shardToMerge: String, streamARN: String? = nil, streamName: String? = nil) {
            self.adjacentShardToMerge = adjacentShardToMerge
            self.shardToMerge = shardToMerge
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.adjacentShardToMerge, name: "adjacentShardToMerge", parent: name, max: 128)
            try self.validate(self.adjacentShardToMerge, name: "adjacentShardToMerge", parent: name, min: 1)
            try self.validate(self.adjacentShardToMerge, name: "adjacentShardToMerge", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.shardToMerge, name: "shardToMerge", parent: name, max: 128)
            try self.validate(self.shardToMerge, name: "shardToMerge", parent: name, min: 1)
            try self.validate(self.shardToMerge, name: "shardToMerge", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case adjacentShardToMerge = "AdjacentShardToMerge"
            case shardToMerge = "ShardToMerge"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct PutRecordInput: AWSEncodableShape {
        /// The data blob to put into the record, which is base64-encoded when the blob is serialized. When the data blob (the payload before base64-encoding) is added to the partition key size, the total size must not exceed the maximum record size (1 MiB).
        public let data: AWSBase64Data
        /// The hash value used to explicitly determine the shard the data record is assigned to by overriding the partition key hash.
        public let explicitHashKey: String?
        /// Determines which shard in the stream the data record is assigned to. Partition keys are Unicode strings with a maximum length limit of 256 characters for each key. Amazon Kinesis Data Streams uses the partition key as input to a hash function that maps the partition key and associated data to a specific shard. Specifically, an MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards. As a result of this hashing mechanism, all data records with the same partition key map to the same shard within the stream.
        public let partitionKey: String
        /// Guarantees strictly increasing sequence numbers, for puts from the same client and to the same partition key. Usage: set the SequenceNumberForOrdering of record n to the sequence number of record n-1 (as returned in the result when putting record n-1). If this parameter is not set, records are coarsely ordered based on arrival time.
        public let sequenceNumberForOrdering: String?
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream to put the data record into.
        public let streamName: String?

        public init(data: AWSBase64Data, explicitHashKey: String? = nil, partitionKey: String, sequenceNumberForOrdering: String? = nil, streamARN: String? = nil, streamName: String? = nil) {
            self.data = data
            self.explicitHashKey = explicitHashKey
            self.partitionKey = partitionKey
            self.sequenceNumberForOrdering = sequenceNumberForOrdering
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.data, name: "data", parent: name, max: 1_048_576)
            try self.validate(self.explicitHashKey, name: "explicitHashKey", parent: name, pattern: "^0|([1-9]\\d{0,38})$")
            try self.validate(self.partitionKey, name: "partitionKey", parent: name, max: 256)
            try self.validate(self.partitionKey, name: "partitionKey", parent: name, min: 1)
            try self.validate(self.sequenceNumberForOrdering, name: "sequenceNumberForOrdering", parent: name, pattern: "^0|([1-9]\\d{0,128})$")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case data = "Data"
            case explicitHashKey = "ExplicitHashKey"
            case partitionKey = "PartitionKey"
            case sequenceNumberForOrdering = "SequenceNumberForOrdering"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct PutRecordOutput: AWSDecodableShape {
        /// The encryption type to use on the record. This parameter can be one of the following values:    NONE: Do not encrypt the records in the stream.    KMS: Use server-side encryption on the records in the stream using a customer-managed Amazon Web Services KMS key.
        public let encryptionType: EncryptionType?
        /// The sequence number identifier that was assigned to the put data record. The sequence number for the record is unique across all records in the stream. A sequence number is the identifier associated with every record put into the stream.
        public let sequenceNumber: String
        /// The shard ID of the shard where the data record was placed.
        public let shardId: String

        public init(encryptionType: EncryptionType? = nil, sequenceNumber: String, shardId: String) {
            self.encryptionType = encryptionType
            self.sequenceNumber = sequenceNumber
            self.shardId = shardId
        }

        private enum CodingKeys: String, CodingKey {
            case encryptionType = "EncryptionType"
            case sequenceNumber = "SequenceNumber"
            case shardId = "ShardId"
        }
    }

    public struct PutRecordsInput: AWSEncodableShape {
        /// The records associated with the request.
        public let records: [PutRecordsRequestEntry]
        /// The ARN of the stream.
        public let streamARN: String?
        /// The stream name associated with the request.
        public let streamName: String?

        public init(records: [PutRecordsRequestEntry], streamARN: String? = nil, streamName: String? = nil) {
            self.records = records
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.records.forEach {
                try $0.validate(name: "\(name).records[]")
            }
            try self.validate(self.records, name: "records", parent: name, max: 500)
            try self.validate(self.records, name: "records", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case records = "Records"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct PutRecordsOutput: AWSDecodableShape {
        /// The encryption type used on the records. This parameter can be one of the following values:    NONE: Do not encrypt the records.    KMS: Use server-side encryption on the records using a customer-managed Amazon Web Services KMS key.
        public let encryptionType: EncryptionType?
        /// The number of unsuccessfully processed records in a PutRecords request.
        public let failedRecordCount: Int?
        /// An array of successfully and unsuccessfully processed record results. A record that is successfully added to a stream includes SequenceNumber and ShardId in the result. A record that fails to be added to a stream includes ErrorCode and ErrorMessage in the result.
        public let records: [PutRecordsResultEntry]

        public init(encryptionType: EncryptionType? = nil, failedRecordCount: Int? = nil, records: [PutRecordsResultEntry]) {
            self.encryptionType = encryptionType
            self.failedRecordCount = failedRecordCount
            self.records = records
        }

        private enum CodingKeys: String, CodingKey {
            case encryptionType = "EncryptionType"
            case failedRecordCount = "FailedRecordCount"
            case records = "Records"
        }
    }

    public struct PutRecordsRequestEntry: AWSEncodableShape {
        /// The data blob to put into the record, which is base64-encoded when the blob is serialized. When the data blob (the payload before base64-encoding) is added to the partition key size, the total size must not exceed the maximum record size (1 MiB).
        public let data: AWSBase64Data
        /// The hash value used to determine explicitly the shard that the data record is assigned to by overriding the partition key hash.
        public let explicitHashKey: String?
        /// Determines which shard in the stream the data record is assigned to. Partition keys are Unicode strings with a maximum length limit of 256 characters for each key. Amazon Kinesis Data Streams uses the partition key as input to a hash function that maps the partition key and associated data to a specific shard. Specifically, an MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards. As a result of this hashing mechanism, all data records with the same partition key map to the same shard within the stream.
        public let partitionKey: String

        public init(data: AWSBase64Data, explicitHashKey: String? = nil, partitionKey: String) {
            self.data = data
            self.explicitHashKey = explicitHashKey
            self.partitionKey = partitionKey
        }

        public func validate(name: String) throws {
            try self.validate(self.data, name: "data", parent: name, max: 1_048_576)
            try self.validate(self.explicitHashKey, name: "explicitHashKey", parent: name, pattern: "^0|([1-9]\\d{0,38})$")
            try self.validate(self.partitionKey, name: "partitionKey", parent: name, max: 256)
            try self.validate(self.partitionKey, name: "partitionKey", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case data = "Data"
            case explicitHashKey = "ExplicitHashKey"
            case partitionKey = "PartitionKey"
        }
    }

    public struct PutRecordsResultEntry: AWSDecodableShape {
        /// The error code for an individual record result. ErrorCodes can be either ProvisionedThroughputExceededException or InternalFailure.
        public let errorCode: String?
        /// The error message for an individual record result. An ErrorCode value of ProvisionedThroughputExceededException has an error message that includes the account ID, stream name, and shard ID. An ErrorCode value of InternalFailure has the error message "Internal Service Failure".
        public let errorMessage: String?
        /// The sequence number for an individual record result.
        public let sequenceNumber: String?
        /// The shard ID for an individual record result.
        public let shardId: String?

        public init(errorCode: String? = nil, errorMessage: String? = nil, sequenceNumber: String? = nil, shardId: String? = nil) {
            self.errorCode = errorCode
            self.errorMessage = errorMessage
            self.sequenceNumber = sequenceNumber
            self.shardId = shardId
        }

        private enum CodingKeys: String, CodingKey {
            case errorCode = "ErrorCode"
            case errorMessage = "ErrorMessage"
            case sequenceNumber = "SequenceNumber"
            case shardId = "ShardId"
        }
    }

    public struct Record: AWSDecodableShape {
        /// The approximate time that the record was inserted into the stream.
        public let approximateArrivalTimestamp: Date?
        /// The data blob. The data in the blob is both opaque and immutable to Kinesis Data Streams, which does not inspect, interpret, or change the data in the blob in any way. When the data blob (the payload before base64-encoding) is added to the partition key size, the total size must not exceed the maximum record size (1 MiB).
        public let data: AWSBase64Data
        /// The encryption type used on the record. This parameter can be one of the following values:    NONE: Do not encrypt the records in the stream.    KMS: Use server-side encryption on the records in the stream using a customer-managed Amazon Web Services KMS key.
        public let encryptionType: EncryptionType?
        /// Identifies which shard in the stream the data record is assigned to.
        public let partitionKey: String
        /// The unique identifier of the record within its shard.
        public let sequenceNumber: String

        public init(approximateArrivalTimestamp: Date? = nil, data: AWSBase64Data, encryptionType: EncryptionType? = nil, partitionKey: String, sequenceNumber: String) {
            self.approximateArrivalTimestamp = approximateArrivalTimestamp
            self.data = data
            self.encryptionType = encryptionType
            self.partitionKey = partitionKey
            self.sequenceNumber = sequenceNumber
        }

        private enum CodingKeys: String, CodingKey {
            case approximateArrivalTimestamp = "ApproximateArrivalTimestamp"
            case data = "Data"
            case encryptionType = "EncryptionType"
            case partitionKey = "PartitionKey"
            case sequenceNumber = "SequenceNumber"
        }
    }

    public struct RegisterStreamConsumerInput: AWSEncodableShape {
        /// For a given Kinesis data stream, each consumer must have a unique name. However, consumer names don't have to be unique across data streams.
        public let consumerName: String
        /// The ARN of the Kinesis data stream that you want to register the consumer with. For more info, see Amazon Resource Names (ARNs) and Amazon Web Services Service Namespaces.
        public let streamARN: String

        public init(consumerName: String, streamARN: String) {
            self.consumerName = consumerName
            self.streamARN = streamARN
        }

        public func validate(name: String) throws {
            try self.validate(self.consumerName, name: "consumerName", parent: name, max: 128)
            try self.validate(self.consumerName, name: "consumerName", parent: name, min: 1)
            try self.validate(self.consumerName, name: "consumerName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
        }

        private enum CodingKeys: String, CodingKey {
            case consumerName = "ConsumerName"
            case streamARN = "StreamARN"
        }
    }

    public struct RegisterStreamConsumerOutput: AWSDecodableShape {
        /// An object that represents the details of the consumer you registered. When you register a consumer, it gets an ARN that is generated by Kinesis Data Streams.
        public let consumer: Consumer

        public init(consumer: Consumer) {
            self.consumer = consumer
        }

        private enum CodingKeys: String, CodingKey {
            case consumer = "Consumer"
        }
    }

    public struct RemoveTagsFromStreamInput: AWSEncodableShape {
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream.
        public let streamName: String?
        /// A list of tag keys. Each corresponding tag is removed from the stream.
        public let tagKeys: [String]

        public init(streamARN: String? = nil, streamName: String? = nil, tagKeys: [String]) {
            self.streamARN = streamARN
            self.streamName = streamName
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 50)
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case streamARN = "StreamARN"
            case streamName = "StreamName"
            case tagKeys = "TagKeys"
        }
    }

    public struct ResourceInUseException: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct ResourceNotFoundException: AWSDecodableShape {
        /// A message that provides information about the error.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct SequenceNumberRange: AWSDecodableShape {
        /// The ending sequence number for the range. Shards that are in the OPEN state have an ending sequence number of null.
        public let endingSequenceNumber: String?
        /// The starting sequence number for the range.
        public let startingSequenceNumber: String

        public init(endingSequenceNumber: String? = nil, startingSequenceNumber: String) {
            self.endingSequenceNumber = endingSequenceNumber
            self.startingSequenceNumber = startingSequenceNumber
        }

        private enum CodingKeys: String, CodingKey {
            case endingSequenceNumber = "EndingSequenceNumber"
            case startingSequenceNumber = "StartingSequenceNumber"
        }
    }

    public struct Shard: AWSDecodableShape {
        /// The shard ID of the shard adjacent to the shard's parent.
        public let adjacentParentShardId: String?
        /// The range of possible hash key values for the shard, which is a set of ordered contiguous positive integers.
        public let hashKeyRange: HashKeyRange
        /// The shard ID of the shard's parent.
        public let parentShardId: String?
        /// The range of possible sequence numbers for the shard.
        public let sequenceNumberRange: SequenceNumberRange
        /// The unique identifier of the shard within the stream.
        public let shardId: String

        public init(adjacentParentShardId: String? = nil, hashKeyRange: HashKeyRange, parentShardId: String? = nil, sequenceNumberRange: SequenceNumberRange, shardId: String) {
            self.adjacentParentShardId = adjacentParentShardId
            self.hashKeyRange = hashKeyRange
            self.parentShardId = parentShardId
            self.sequenceNumberRange = sequenceNumberRange
            self.shardId = shardId
        }

        private enum CodingKeys: String, CodingKey {
            case adjacentParentShardId = "AdjacentParentShardId"
            case hashKeyRange = "HashKeyRange"
            case parentShardId = "ParentShardId"
            case sequenceNumberRange = "SequenceNumberRange"
            case shardId = "ShardId"
        }
    }

    public struct ShardFilter: AWSEncodableShape {
        /// The exclusive start shardID speified in the ShardFilter parameter. This property can only be used if the AFTER_SHARD_ID shard type is specified.
        public let shardId: String?
        /// The timestamps specified in the ShardFilter parameter. A timestamp is a Unix epoch date with precision in milliseconds. For example, 2016-04-04T19:58:46.480-00:00 or 1459799926.480. This property can only be used if FROM_TIMESTAMP or AT_TIMESTAMP shard types are specified.
        public let timestamp: Date?
        /// The shard type specified in the ShardFilter parameter. This is a required property of the ShardFilter parameter. You can specify the following valid values:     AFTER_SHARD_ID - the response includes all the shards, starting with the shard whose ID immediately follows the ShardId that you provided.     AT_TRIM_HORIZON - the response includes all the shards that were open at TRIM_HORIZON.    FROM_TRIM_HORIZON - (default), the response includes all the shards within the retention period of the data stream (trim to tip).    AT_LATEST - the response includes only the currently open shards of the data stream.    AT_TIMESTAMP - the response includes all shards whose start timestamp is less than or equal to the given timestamp and end timestamp is greater than or equal to the given timestamp or still open.     FROM_TIMESTAMP - the response incldues all closed shards whose end timestamp is greater than or equal to the given timestamp and also all open shards. Corrected to TRIM_HORIZON of the data stream if FROM_TIMESTAMP is less than the TRIM_HORIZON value.
        public let type: ShardFilterType

        public init(shardId: String? = nil, timestamp: Date? = nil, type: ShardFilterType) {
            self.shardId = shardId
            self.timestamp = timestamp
            self.type = type
        }

        public func validate(name: String) throws {
            try self.validate(self.shardId, name: "shardId", parent: name, max: 128)
            try self.validate(self.shardId, name: "shardId", parent: name, min: 1)
            try self.validate(self.shardId, name: "shardId", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case shardId = "ShardId"
            case timestamp = "Timestamp"
            case type = "Type"
        }
    }

    public struct SplitShardInput: AWSEncodableShape {
        /// A hash key value for the starting hash key of one of the child shards created by the split. The hash key range for a given shard constitutes a set of ordered contiguous positive integers. The value for NewStartingHashKey must be in the range of hash keys being mapped into the shard. The NewStartingHashKey hash key value and all higher hash key values in hash key range are distributed to one of the child shards. All the lower hash key values in the range are distributed to the other child shard.
        public let newStartingHashKey: String
        /// The shard ID of the shard to split.
        public let shardToSplit: String
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream for the shard split.
        public let streamName: String?

        public init(newStartingHashKey: String, shardToSplit: String, streamARN: String? = nil, streamName: String? = nil) {
            self.newStartingHashKey = newStartingHashKey
            self.shardToSplit = shardToSplit
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.newStartingHashKey, name: "newStartingHashKey", parent: name, pattern: "^0|([1-9]\\d{0,38})$")
            try self.validate(self.shardToSplit, name: "shardToSplit", parent: name, max: 128)
            try self.validate(self.shardToSplit, name: "shardToSplit", parent: name, min: 1)
            try self.validate(self.shardToSplit, name: "shardToSplit", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case newStartingHashKey = "NewStartingHashKey"
            case shardToSplit = "ShardToSplit"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct StartStreamEncryptionInput: AWSEncodableShape {
        /// The encryption type to use. The only valid value is KMS.
        public let encryptionType: EncryptionType
        /// The GUID for the customer-managed Amazon Web Services KMS key to use for encryption. This value can be a globally unique identifier, a fully specified Amazon Resource Name (ARN) to either an alias or a key, or an alias name prefixed by "alias/".You can also use a master key owned by Kinesis Data Streams by specifying the alias aws/kinesis.   Key ARN example: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012    Alias ARN example: arn:aws:kms:us-east-1:123456789012:alias/MyAliasName    Globally unique key ID example: 12345678-1234-1234-1234-123456789012    Alias name example: alias/MyAliasName    Master key owned by Kinesis Data Streams: alias/aws/kinesis
        public let keyId: String
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream for which to start encrypting records.
        public let streamName: String?

        public init(encryptionType: EncryptionType, keyId: String, streamARN: String? = nil, streamName: String? = nil) {
            self.encryptionType = encryptionType
            self.keyId = keyId
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.keyId, name: "keyId", parent: name, max: 2048)
            try self.validate(self.keyId, name: "keyId", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case encryptionType = "EncryptionType"
            case keyId = "KeyId"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct StartingPosition: AWSEncodableShape {
        /// The sequence number of the data record in the shard from which to start streaming. To specify a sequence number, set StartingPosition to AT_SEQUENCE_NUMBER or AFTER_SEQUENCE_NUMBER.
        public let sequenceNumber: String?
        /// The time stamp of the data record from which to start reading. To specify a time stamp, set StartingPosition to Type AT_TIMESTAMP. A time stamp is the Unix epoch date with precision in milliseconds. For example, 2016-04-04T19:58:46.480-00:00 or 1459799926.480. If a record with this exact time stamp does not exist, records will be streamed from the next (later) record. If the time stamp is older than the current trim horizon, records will be streamed from the oldest untrimmed data record (TRIM_HORIZON).
        public let timestamp: Date?
        /// You can set the starting position to one of the following values:  AT_SEQUENCE_NUMBER: Start streaming from the position denoted by the sequence number specified in the SequenceNumber field.  AFTER_SEQUENCE_NUMBER: Start streaming right after the position denoted by the sequence number specified in the SequenceNumber field.  AT_TIMESTAMP: Start streaming from the position denoted by the time stamp specified in the Timestamp field.  TRIM_HORIZON: Start streaming at the last untrimmed record in the shard, which is the oldest data record in the shard.  LATEST: Start streaming just after the most recent record in the shard, so that you always read the most recent data in the shard.
        public let type: ShardIteratorType

        public init(sequenceNumber: String? = nil, timestamp: Date? = nil, type: ShardIteratorType) {
            self.sequenceNumber = sequenceNumber
            self.timestamp = timestamp
            self.type = type
        }

        public func validate(name: String) throws {
            try self.validate(self.sequenceNumber, name: "sequenceNumber", parent: name, pattern: "^0|([1-9]\\d{0,128})$")
        }

        private enum CodingKeys: String, CodingKey {
            case sequenceNumber = "SequenceNumber"
            case timestamp = "Timestamp"
            case type = "Type"
        }
    }

    public struct StopStreamEncryptionInput: AWSEncodableShape {
        /// The encryption type. The only valid value is KMS.
        public let encryptionType: EncryptionType
        /// The GUID for the customer-managed Amazon Web Services KMS key to use for encryption. This value can be a globally unique identifier, a fully specified Amazon Resource Name (ARN) to either an alias or a key, or an alias name prefixed by "alias/".You can also use a master key owned by Kinesis Data Streams by specifying the alias aws/kinesis.   Key ARN example: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012    Alias ARN example: arn:aws:kms:us-east-1:123456789012:alias/MyAliasName    Globally unique key ID example: 12345678-1234-1234-1234-123456789012    Alias name example: alias/MyAliasName    Master key owned by Kinesis Data Streams: alias/aws/kinesis
        public let keyId: String
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream on which to stop encrypting records.
        public let streamName: String?

        public init(encryptionType: EncryptionType, keyId: String, streamARN: String? = nil, streamName: String? = nil) {
            self.encryptionType = encryptionType
            self.keyId = keyId
            self.streamARN = streamARN
            self.streamName = streamName
        }

        public func validate(name: String) throws {
            try self.validate(self.keyId, name: "keyId", parent: name, max: 2048)
            try self.validate(self.keyId, name: "keyId", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case encryptionType = "EncryptionType"
            case keyId = "KeyId"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
        }
    }

    public struct StreamDescription: AWSDecodableShape {
        /// The server-side encryption type used on the stream. This parameter can be one of the following values:    NONE: Do not encrypt the records in the stream.    KMS: Use server-side encryption on the records in the stream using a customer-managed Amazon Web Services KMS key.
        public let encryptionType: EncryptionType?
        /// Represents the current enhanced monitoring settings of the stream.
        public let enhancedMonitoring: [EnhancedMetrics]
        /// If set to true, more shards in the stream are available to describe.
        public let hasMoreShards: Bool
        /// The GUID for the customer-managed Amazon Web Services KMS key to use for encryption. This value can be a globally unique identifier, a fully specified ARN to either an alias or a key, or an alias name prefixed by "alias/".You can also use a master key owned by Kinesis Data Streams by specifying the alias aws/kinesis.   Key ARN example: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012    Alias ARN example: arn:aws:kms:us-east-1:123456789012:alias/MyAliasName    Globally unique key ID example: 12345678-1234-1234-1234-123456789012    Alias name example: alias/MyAliasName    Master key owned by Kinesis Data Streams: alias/aws/kinesis
        public let keyId: String?
        /// The current retention period, in hours. Minimum value of 24. Maximum value of 168.
        public let retentionPeriodHours: Int
        /// The shards that comprise the stream.
        public let shards: [Shard]
        /// The Amazon Resource Name (ARN) for the stream being described.
        public let streamARN: String
        /// The approximate time that the stream was created.
        public let streamCreationTimestamp: Date
        ///  Specifies the capacity mode to which you want to set your data stream. Currently, in Kinesis Data Streams, you can choose between an on-demand capacity mode and a provisioned capacity mode for your data streams.
        public let streamModeDetails: StreamModeDetails?
        /// The name of the stream being described.
        public let streamName: String
        /// The current status of the stream being described. The stream status is one of the following states:    CREATING - The stream is being created. Kinesis Data Streams immediately returns and sets StreamStatus to CREATING.    DELETING - The stream is being deleted. The specified stream is in the DELETING state until Kinesis Data Streams completes the deletion.    ACTIVE - The stream exists and is ready for read and write operations or deletion. You should perform read and write operations only on an ACTIVE stream.    UPDATING - Shards in the stream are being merged or split. Read and write operations continue to work while the stream is in the UPDATING state.
        public let streamStatus: StreamStatus

        public init(encryptionType: EncryptionType? = nil, enhancedMonitoring: [EnhancedMetrics], hasMoreShards: Bool, keyId: String? = nil, retentionPeriodHours: Int, shards: [Shard], streamARN: String, streamCreationTimestamp: Date, streamModeDetails: StreamModeDetails? = nil, streamName: String, streamStatus: StreamStatus) {
            self.encryptionType = encryptionType
            self.enhancedMonitoring = enhancedMonitoring
            self.hasMoreShards = hasMoreShards
            self.keyId = keyId
            self.retentionPeriodHours = retentionPeriodHours
            self.shards = shards
            self.streamARN = streamARN
            self.streamCreationTimestamp = streamCreationTimestamp
            self.streamModeDetails = streamModeDetails
            self.streamName = streamName
            self.streamStatus = streamStatus
        }

        private enum CodingKeys: String, CodingKey {
            case encryptionType = "EncryptionType"
            case enhancedMonitoring = "EnhancedMonitoring"
            case hasMoreShards = "HasMoreShards"
            case keyId = "KeyId"
            case retentionPeriodHours = "RetentionPeriodHours"
            case shards = "Shards"
            case streamARN = "StreamARN"
            case streamCreationTimestamp = "StreamCreationTimestamp"
            case streamModeDetails = "StreamModeDetails"
            case streamName = "StreamName"
            case streamStatus = "StreamStatus"
        }
    }

    public struct StreamDescriptionSummary: AWSDecodableShape {
        /// The number of enhanced fan-out consumers registered with the stream.
        public let consumerCount: Int?
        /// The encryption type used. This value is one of the following:    KMS     NONE
        public let encryptionType: EncryptionType?
        /// Represents the current enhanced monitoring settings of the stream.
        public let enhancedMonitoring: [EnhancedMetrics]
        /// The GUID for the customer-managed Amazon Web Services KMS key to use for encryption. This value can be a globally unique identifier, a fully specified ARN to either an alias or a key, or an alias name prefixed by "alias/".You can also use a master key owned by Kinesis Data Streams by specifying the alias aws/kinesis.   Key ARN example: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012    Alias ARN example:  arn:aws:kms:us-east-1:123456789012:alias/MyAliasName    Globally unique key ID example: 12345678-1234-1234-1234-123456789012    Alias name example: alias/MyAliasName    Master key owned by Kinesis Data Streams: alias/aws/kinesis
        public let keyId: String?
        /// The number of open shards in the stream.
        public let openShardCount: Int
        /// The current retention period, in hours.
        public let retentionPeriodHours: Int
        /// The Amazon Resource Name (ARN) for the stream being described.
        public let streamARN: String
        /// The approximate time that the stream was created.
        public let streamCreationTimestamp: Date
        ///  Specifies the capacity mode to which you want to set your data stream. Currently, in Kinesis Data Streams, you can choose between an on-demand ycapacity mode and a provisioned capacity mode for your data streams.
        public let streamModeDetails: StreamModeDetails?
        /// The name of the stream being described.
        public let streamName: String
        /// The current status of the stream being described. The stream status is one of the following states:    CREATING - The stream is being created. Kinesis Data Streams immediately returns and sets StreamStatus to CREATING.    DELETING - The stream is being deleted. The specified stream is in the DELETING state until Kinesis Data Streams completes the deletion.    ACTIVE - The stream exists and is ready for read and write operations or deletion. You should perform read and write operations only on an ACTIVE stream.    UPDATING - Shards in the stream are being merged or split. Read and write operations continue to work while the stream is in the UPDATING state.
        public let streamStatus: StreamStatus

        public init(consumerCount: Int? = nil, encryptionType: EncryptionType? = nil, enhancedMonitoring: [EnhancedMetrics], keyId: String? = nil, openShardCount: Int, retentionPeriodHours: Int, streamARN: String, streamCreationTimestamp: Date, streamModeDetails: StreamModeDetails? = nil, streamName: String, streamStatus: StreamStatus) {
            self.consumerCount = consumerCount
            self.encryptionType = encryptionType
            self.enhancedMonitoring = enhancedMonitoring
            self.keyId = keyId
            self.openShardCount = openShardCount
            self.retentionPeriodHours = retentionPeriodHours
            self.streamARN = streamARN
            self.streamCreationTimestamp = streamCreationTimestamp
            self.streamModeDetails = streamModeDetails
            self.streamName = streamName
            self.streamStatus = streamStatus
        }

        private enum CodingKeys: String, CodingKey {
            case consumerCount = "ConsumerCount"
            case encryptionType = "EncryptionType"
            case enhancedMonitoring = "EnhancedMonitoring"
            case keyId = "KeyId"
            case openShardCount = "OpenShardCount"
            case retentionPeriodHours = "RetentionPeriodHours"
            case streamARN = "StreamARN"
            case streamCreationTimestamp = "StreamCreationTimestamp"
            case streamModeDetails = "StreamModeDetails"
            case streamName = "StreamName"
            case streamStatus = "StreamStatus"
        }
    }

    public struct StreamModeDetails: AWSEncodableShape & AWSDecodableShape {
        ///  Specifies the capacity mode to which you want to set your data stream. Currently, in Kinesis Data Streams, you can choose between an on-demand capacity mode and a provisioned capacity mode for your data streams.
        public let streamMode: StreamMode

        public init(streamMode: StreamMode) {
            self.streamMode = streamMode
        }

        private enum CodingKeys: String, CodingKey {
            case streamMode = "StreamMode"
        }
    }

    public struct StreamSummary: AWSDecodableShape {
        /// The ARN of the stream.
        public let streamARN: String
        /// The timestamp at which the stream was created.
        public let streamCreationTimestamp: Date?
        public let streamModeDetails: StreamModeDetails?
        /// The name of a stream.
        public let streamName: String
        /// The status of the stream.
        public let streamStatus: StreamStatus

        public init(streamARN: String, streamCreationTimestamp: Date? = nil, streamModeDetails: StreamModeDetails? = nil, streamName: String, streamStatus: StreamStatus) {
            self.streamARN = streamARN
            self.streamCreationTimestamp = streamCreationTimestamp
            self.streamModeDetails = streamModeDetails
            self.streamName = streamName
            self.streamStatus = streamStatus
        }

        private enum CodingKeys: String, CodingKey {
            case streamARN = "StreamARN"
            case streamCreationTimestamp = "StreamCreationTimestamp"
            case streamModeDetails = "StreamModeDetails"
            case streamName = "StreamName"
            case streamStatus = "StreamStatus"
        }
    }

    public struct SubscribeToShardEvent: AWSDecodableShape {
        /// The list of the child shards of the current shard, returned only at the end of the current shard.
        public let childShards: [ChildShard]?
        /// Use this as SequenceNumber in the next call to SubscribeToShard, with StartingPosition set to AT_SEQUENCE_NUMBER or AFTER_SEQUENCE_NUMBER. Use ContinuationSequenceNumber for checkpointing because it captures your shard progress even when no data is written to the shard.
        public let continuationSequenceNumber: String
        /// The number of milliseconds the read records are from the tip of the stream, indicating how far behind current time the consumer is. A value of zero indicates that record processing is caught up, and there are no new records to process at this moment.
        public let millisBehindLatest: Int64
        public let records: [Record]

        public init(childShards: [ChildShard]? = nil, continuationSequenceNumber: String, millisBehindLatest: Int64, records: [Record]) {
            self.childShards = childShards
            self.continuationSequenceNumber = continuationSequenceNumber
            self.millisBehindLatest = millisBehindLatest
            self.records = records
        }

        private enum CodingKeys: String, CodingKey {
            case childShards = "ChildShards"
            case continuationSequenceNumber = "ContinuationSequenceNumber"
            case millisBehindLatest = "MillisBehindLatest"
            case records = "Records"
        }
    }

    public struct SubscribeToShardInput: AWSEncodableShape {
        /// For this parameter, use the value you obtained when you called RegisterStreamConsumer.
        public let consumerARN: String
        /// The ID of the shard you want to subscribe to. To see a list of all the shards for a given stream, use ListShards.
        public let shardId: String
        /// The starting position in the data stream from which to start streaming.
        public let startingPosition: StartingPosition

        public init(consumerARN: String, shardId: String, startingPosition: StartingPosition) {
            self.consumerARN = consumerARN
            self.shardId = shardId
            self.startingPosition = startingPosition
        }

        public func validate(name: String) throws {
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, max: 2048)
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, min: 1)
            try self.validate(self.consumerARN, name: "consumerARN", parent: name, pattern: "^(arn):aws.*:kinesis:.*:\\d{12}:.*stream\\/[a-zA-Z0-9_.-]+\\/consumer\\/[a-zA-Z0-9_.-]+:[0-9]+$")
            try self.validate(self.shardId, name: "shardId", parent: name, max: 128)
            try self.validate(self.shardId, name: "shardId", parent: name, min: 1)
            try self.validate(self.shardId, name: "shardId", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.startingPosition.validate(name: "\(name).startingPosition")
        }

        private enum CodingKeys: String, CodingKey {
            case consumerARN = "ConsumerARN"
            case shardId = "ShardId"
            case startingPosition = "StartingPosition"
        }
    }

    public struct SubscribeToShardOutput: AWSDecodableShape {
        /// The event stream that your consumer can use to read records from the shard.
        public let eventStream: SubscribeToShardEventStream

        public init(eventStream: SubscribeToShardEventStream) {
            self.eventStream = eventStream
        }

        private enum CodingKeys: String, CodingKey {
            case eventStream = "EventStream"
        }
    }

    public struct Tag: AWSDecodableShape {
        /// A unique identifier for the tag. Maximum length: 128 characters. Valid characters: Unicode letters, digits, white space, _ . / = + - % @
        public let key: String
        /// An optional string, typically used to describe or define the tag. Maximum length: 256 characters. Valid characters: Unicode letters, digits, white space, _ . / = + - % @
        public let value: String?

        public init(key: String, value: String? = nil) {
            self.key = key
            self.value = value
        }

        private enum CodingKeys: String, CodingKey {
            case key = "Key"
            case value = "Value"
        }
    }

    public struct UpdateShardCountInput: AWSEncodableShape {
        /// The scaling type. Uniform scaling creates shards of equal size.
        public let scalingType: ScalingType
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream.
        public let streamName: String?
        /// The new number of shards. This value has the following default limits. By default, you cannot do the following:    Set this value to more than double your current shard count for a stream.   Set this value below half your current shard count for a stream.   Set this value to more than 10000 shards in a stream (the default limit for shard count per stream is 10000 per account per region), unless you request a limit increase.   Scale a stream with more than 10000 shards down unless you set this value to less than 10000 shards.
        public let targetShardCount: Int

        public init(scalingType: ScalingType, streamARN: String? = nil, streamName: String? = nil, targetShardCount: Int) {
            self.scalingType = scalingType
            self.streamARN = streamARN
            self.streamName = streamName
            self.targetShardCount = targetShardCount
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
            try self.validate(self.streamName, name: "streamName", parent: name, max: 128)
            try self.validate(self.streamName, name: "streamName", parent: name, min: 1)
            try self.validate(self.streamName, name: "streamName", parent: name, pattern: "^[a-zA-Z0-9_.-]+$")
            try self.validate(self.targetShardCount, name: "targetShardCount", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case scalingType = "ScalingType"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
            case targetShardCount = "TargetShardCount"
        }
    }

    public struct UpdateShardCountOutput: AWSDecodableShape {
        /// The current number of shards.
        public let currentShardCount: Int?
        /// The ARN of the stream.
        public let streamARN: String?
        /// The name of the stream.
        public let streamName: String?
        /// The updated number of shards.
        public let targetShardCount: Int?

        public init(currentShardCount: Int? = nil, streamARN: String? = nil, streamName: String? = nil, targetShardCount: Int? = nil) {
            self.currentShardCount = currentShardCount
            self.streamARN = streamARN
            self.streamName = streamName
            self.targetShardCount = targetShardCount
        }

        private enum CodingKeys: String, CodingKey {
            case currentShardCount = "CurrentShardCount"
            case streamARN = "StreamARN"
            case streamName = "StreamName"
            case targetShardCount = "TargetShardCount"
        }
    }

    public struct UpdateStreamModeInput: AWSEncodableShape {
        ///  Specifies the ARN of the data stream whose capacity mode you want to update.
        public let streamARN: String
        ///  Specifies the capacity mode to which you want to set your data stream. Currently, in Kinesis Data Streams, you can choose between an on-demand capacity mode and a provisioned capacity mode for your data streams.
        public let streamModeDetails: StreamModeDetails

        public init(streamARN: String, streamModeDetails: StreamModeDetails) {
            self.streamARN = streamARN
            self.streamModeDetails = streamModeDetails
        }

        public func validate(name: String) throws {
            try self.validate(self.streamARN, name: "streamARN", parent: name, max: 2048)
            try self.validate(self.streamARN, name: "streamARN", parent: name, min: 1)
            try self.validate(self.streamARN, name: "streamARN", parent: name, pattern: "^arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+$")
        }

        private enum CodingKeys: String, CodingKey {
            case streamARN = "StreamARN"
            case streamModeDetails = "StreamModeDetails"
        }
    }
}

// MARK: - Errors

/// Error enum for Kinesis
public struct KinesisErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case expiredIteratorException = "ExpiredIteratorException"
        case expiredNextTokenException = "ExpiredNextTokenException"
        case internalFailureException = "InternalFailureException"
        case invalidArgumentException = "InvalidArgumentException"
        case kmsAccessDeniedException = "KMSAccessDeniedException"
        case kmsDisabledException = "KMSDisabledException"
        case kmsInvalidStateException = "KMSInvalidStateException"
        case kmsNotFoundException = "KMSNotFoundException"
        case kmsOptInRequired = "KMSOptInRequired"
        case kmsThrottlingException = "KMSThrottlingException"
        case limitExceededException = "LimitExceededException"
        case provisionedThroughputExceededException = "ProvisionedThroughputExceededException"
        case resourceInUseException = "ResourceInUseException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize Kinesis
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// Specifies that you do not have the permissions required to perform this operation.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// The provided iterator exceeds the maximum age allowed.
    public static var expiredIteratorException: Self { .init(.expiredIteratorException) }
    /// The pagination token passed to the operation is expired.
    public static var expiredNextTokenException: Self { .init(.expiredNextTokenException) }
    /// The processing of the request failed because of an unknown error, exception, or failure.
    public static var internalFailureException: Self { .init(.internalFailureException) }
    /// A specified parameter exceeds its restrictions, is not supported, or can&#39;t be used. For more information, see the returned message.
    public static var invalidArgumentException: Self { .init(.invalidArgumentException) }
    /// The ciphertext references a key that doesn&#39;t exist or that you don&#39;t have access to.
    public static var kmsAccessDeniedException: Self { .init(.kmsAccessDeniedException) }
    /// The request was rejected because the specified customer master key (CMK) isn&#39;t enabled.
    public static var kmsDisabledException: Self { .init(.kmsDisabledException) }
    /// The request was rejected because the state of the specified resource isn&#39;t valid for this request. For more information, see How Key State Affects Use of a Customer Master Key in the Amazon Web Services Key Management Service Developer Guide.
    public static var kmsInvalidStateException: Self { .init(.kmsInvalidStateException) }
    /// The request was rejected because the specified entity or resource can&#39;t be found.
    public static var kmsNotFoundException: Self { .init(.kmsNotFoundException) }
    /// The Amazon Web Services access key ID needs a subscription for the service.
    public static var kmsOptInRequired: Self { .init(.kmsOptInRequired) }
    /// The request was denied due to request throttling. For more information about throttling, see Limits in the Amazon Web Services Key Management Service Developer Guide.
    public static var kmsThrottlingException: Self { .init(.kmsThrottlingException) }
    /// The requested resource exceeds the maximum number allowed, or the number of concurrent stream requests exceeds the maximum number allowed.
    public static var limitExceededException: Self { .init(.limitExceededException) }
    /// The request rate for the stream is too high, or the requested data is too large for the available throughput. Reduce the frequency or size of your requests. For more information, see Streams Limits in the Amazon Kinesis Data Streams Developer Guide, and Error Retries and Exponential Backoff in Amazon Web Services in the Amazon Web Services General Reference.
    public static var provisionedThroughputExceededException: Self { .init(.provisionedThroughputExceededException) }
    /// The resource is not available for this operation. For successful operation, the resource must be in the ACTIVE state.
    public static var resourceInUseException: Self { .init(.resourceInUseException) }
    /// The requested resource could not be found. The stream might not be specified correctly.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// Specifies that you tried to invoke this API for a data stream with the on-demand capacity mode. This API is only supported for data streams with the provisioned capacity mode.
    public static var validationException: Self { .init(.validationException) }
}

extension KinesisErrorType: Equatable {
    public static func == (lhs: KinesisErrorType, rhs: KinesisErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension KinesisErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
